package student.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import student.world.*;

public class ControlPanel extends JPanel {
	
	private CritterWorld world;
	private final WorldViewPanel view;
	private JButton[] actionButtons;
	private JButton playButton;
	private JButton waitButton;
	private JButton incrementButton;
	private JSlider speedSlider;
	
	private JPanel worldPanel;
	private JPanel critterPanel;
	
	private boolean allWait;
	private Timer timer;
	private boolean playing;
	private final Color bkg = new Color(255,99,71);

	public ControlPanel(CritterWorld w, WorldViewPanel worldView) {
		world = w;
		view = worldView;
		view.addExternalMouseListener(new WorldViewClickListener());
		
		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		worldPanel = new JPanel(new GridLayout(5, 1));
		critterPanel = new JPanel(new GridLayout(5, 2));
		
		makeButtons();
		
		JPanel wLabelPanel = new JPanel(){
			public Dimension getMaximumSize(){
				return new Dimension(500, 20);
			}
		};
		wLabelPanel.setBackground(bkg);
		wLabelPanel.add(new JLabel("World Controls"));
		add(wLabelPanel);
		add(worldPanel);
		
		worldPanel.add(playButton);
		worldPanel.add(new JLabel("Steps per second:"));
		worldPanel.add(speedSlider);
		worldPanel.add(waitButton);
		worldPanel.add(incrementButton);
		
		JPanel cLabelPanel = new JPanel(){
			public Dimension getMaximumSize(){
				return new Dimension(500, 20);
			}
		};
		cLabelPanel.setBackground(bkg);
		cLabelPanel.add(new JLabel("Critter Controls"));
		add(cLabelPanel);
		add(critterPanel);
		
		for (int i = 0; i < 10; i++)
			critterPanel.add(actionButtons[(i+1)%10]);
		
		timer = new Timer((int)(1.0/speedSlider.getValue() * 1000), new TimerListener());
		
		setBackground(bkg);
		setBorder(new LineBorder(bkg, 10));
	}
	
	public int getPlaySpeed(){
		return speedSlider.getValue();
	}
	
	private void makeButtons() {
		playButton = new JButton("Play");
		playButton.addActionListener(new PlayPauseListener());
		waitButton = new JButton("Critters Always Wait");
		waitButton.addActionListener(new WaitListener());
		incrementButton = new JButton("Next Time Step");
		incrementButton.addActionListener(new IncrementListener());
		String[] actions = {"Wait", "Forward", "Backward", "Left", "Right", "Eat", "Attack", "Grow", "Bud", "Mate"};
		actionButtons = new JButton[10];
		for (int i = 0; i < 10; i++){
			actionButtons[i] = new JButton(actions[i]);
			actionButtons[i].addActionListener(new CritterButtonListener(i));
		}
		speedSlider = new JSlider(1, 30);
		speedSlider.setValue(1);
		speedSlider.setLabelTable(speedSlider.createStandardLabels(10));
		speedSlider.setMajorTickSpacing(10);
		speedSlider.setMinorTickSpacing(1);
		speedSlider.setPaintLabels(true);
		speedSlider.setPaintTicks(true);
		speedSlider.addChangeListener(new SpeedSliderListener());
	}
	
	private void pauseWorld(){
		timer.stop();
		playing = false;
		playButton.setText("Play");
	}
	
	private void playWorld(){
		timer.start();
		playing = true;
		playButton.setText("Pause");	
	}
	
	private class CritterButtonListener implements ActionListener {
		private int command;
		
		public CritterButtonListener(int cmd) {
			command = cmd;
		}
		
		public void actionPerformed(ActionEvent e) {
			if(playing)
				pauseWorld();
			world.incrementTimestep(allWait, view.getSelectedCritter(), command);
			SwingUtilities.getWindowAncestor(getParent()).repaint();
		}
	}	
	
	private class PlayPauseListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if(playing)
				pauseWorld();
			else
				playWorld();				
		}
	}
	
	private class WaitListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if(allWait){
				allWait = false;
				waitButton.setText("Critters Always Wait");
			} else{
				allWait = true;
				waitButton.setText("Critters Act Randomly");				
			}
		}
	}
	
	private class TimerListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			world.incrementTimestep(allWait);
			SwingUtilities.getWindowAncestor(getParent()).repaint();
		}
	}
	
	private class IncrementListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if(playing)
				pauseWorld();
			world.incrementTimestep(allWait);
			SwingUtilities.getWindowAncestor(getParent()).repaint();
		}
	}
	
	/**
	 * Designed for JSlider, never use with anything else
	 */
	private class SpeedSliderListener implements ChangeListener{
		public void stateChanged(ChangeEvent e) {
			JSlider slider = (JSlider) e.getSource();
			timer.setDelay((int)(1.0/slider.getValue() * 1000));
		}
	}
	
	private class WorldViewClickListener extends MouseAdapter{
		public void mouseClicked(MouseEvent e){
			if(playing)
				pauseWorld();
		}
	}
}
